using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace EasyElasticLogger.NETFramework.ES.Configuration
{
    /// <summary>
    /// 配置提供程序，支持多种配置方式
    /// </summary>
    public static class ConfigurationProvider
    {
        /// <summary>
        /// 从.app.config或.web.config文件加载配置
        /// </summary>
        /// <returns>日志记录器配置</returns>
        public static LoggerConfiguration FromAppConfig()
        {
            return FromAppConfig(GetCurrentEnvironment());
        }

        /// <summary>
        /// 从.app.config或.web.config文件加载指定环境的配置
        /// </summary>
        /// <param name="environment">环境名称（如：Development、Test、Production）</param>
        /// <returns>日志记录器配置</returns>
        public static LoggerConfiguration FromAppConfig(string environment)
        {
            return FromMappedConfig(null, environment);
        }

        /// <summary>
        /// 从指定的配置文件加载配置（兼容AutoCAD二次开发）
        /// </summary>
        /// <param name="configFilePath">配置文件路径</param>
        /// <returns>日志记录器配置</returns>
        public static LoggerConfiguration FromMappedConfig(string configFilePath)
        {
            return FromMappedConfig(configFilePath, GetCurrentEnvironment());
        }

        /// <summary>
        /// 从指定的配置文件加载指定环境的配置（兼容AutoCAD二次开发）
        /// </summary>
        /// <param name="configFilePath">配置文件路径</param>
        /// <param name="environment">环境名称（如：Development、Test、Production）</param>
        /// <returns>日志记录器配置</returns>
        public static LoggerConfiguration FromMappedConfig(string configFilePath, string environment)
        {
            var config = new LoggerConfiguration();

            try
            {
                // 获取配置对象
               System.Configuration.Configuration configuration = null;
                
                if (string.IsNullOrEmpty(configFilePath))
                {
                    // 使用默认配置文件
                    configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                }
                else
                {
                    // 使用指定配置文件（兼容AutoCAD二次开发）
                    if (!File.Exists(configFilePath))
                        throw new FileNotFoundException($"配置文件未找到: {configFilePath}");

                    var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = configFilePath };
                    configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                }

                // 根据环境获取配置节名称
                string loggerSectionName = string.IsNullOrEmpty(environment) ? "elasticLogger" : $"elasticLogger.{environment}";
                string clusterSectionName = string.IsNullOrEmpty(environment) ? "elasticCluster" : $"elasticCluster.{environment}";

                // 读取日志记录器配置
                var loggerSection = configuration.GetSection(loggerSectionName) as ConfigurationSection;
                // 如果特定环境的配置不存在，则使用默认配置
                if (loggerSection == null && !string.IsNullOrEmpty(environment))
                {
                    loggerSection = configuration.GetSection("elasticLogger") as ConfigurationSection;
                }

                if (loggerSection != null)
                {
                    config.Enabled = GetConfigValue<bool>(loggerSection, "enabled", true);
                    config.IndexPrefix = GetConfigValue<string>(loggerSection, "indexPrefix", "app-log");
                    config.ApplicationName = GetConfigValue<string>(loggerSection, "applicationName", "DefaultApp");
                    config.BatchSize = GetConfigValue<int>(loggerSection, "batchSize", 100);
                    config.TimeoutMs = GetConfigValue<int>(loggerSection, "timeoutMs", 10000);

                    // 读取索引策略
                    var indexStrategy = GetConfigValue<string>(loggerSection, "indexStrategy", "DailyRolling");
                    config.IndexStrategy = Enum.TryParse<IndexStrategy>(indexStrategy, true, out var strategy) 
                        ? strategy : IndexStrategy.DailyRolling;

                    if (config.IndexStrategy == IndexStrategy.Fixed)
                    {
                        config.FixedIndexName = GetConfigValue<string>(loggerSection, "fixedIndexName", "app-log");
                    }
                }

                // 读取集群配置
                var clusterSection = configuration.GetSection(clusterSectionName) as ConfigurationSection;
                // 如果特定环境的配置不存在，则使用默认配置
                if (clusterSection == null && !string.IsNullOrEmpty(environment))
                {
                    clusterSection = configuration.GetSection("elasticCluster") as ConfigurationSection;
                }

                if (clusterSection != null)
                {
                    config.Cluster.Username = GetConfigValue<string>(clusterSection, "username", null);
                    config.Cluster.Password = GetConfigValue<string>(clusterSection, "password", null);
                    config.Cluster.UseSsl = GetConfigValue<bool>(clusterSection, "useSsl", false);
                    config.Cluster.SkipSslVerification = GetConfigValue<bool>(clusterSection, "skipSslVerification", false);
                    config.Cluster.ConnectionTimeoutMs = GetConfigValue<int>(clusterSection, "connectionTimeoutMs", 5000);
                    config.Cluster.MaxRetries = GetConfigValue<int>(clusterSection, "maxRetries", 2);

                    var nodes = GetConfigValue<string>(clusterSection, "nodes", null);
                    if (!string.IsNullOrEmpty(nodes))
                    {
                        config.Cluster.Nodes = nodes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                            .Select(n => n.Trim())
                            .ToList();
                    }
                }
            }
            catch (Exception ex)
            {
                // 记录异常但不抛出，使用默认配置
                System.Diagnostics.Trace.WriteLine($"[ConfigurationProvider] 从配置文件加载配置时出错: {ex.Message}");
            }

            return config;
        }

        /// <summary>
        /// 从JSON文件加载配置
        /// </summary>
        /// <param name="jsonFilePath">JSON文件路径</param>
        /// <returns>日志记录器配置</returns>
        public static LoggerConfiguration FromJsonFile(string jsonFilePath)
        {
            return FromJsonFile(jsonFilePath, GetCurrentEnvironment());
        }

        /// <summary>
        /// 从JSON文件加载指定环境的配置
        /// </summary>
        /// <param name="jsonFilePath">JSON文件路径</param>
        /// <param name="environment">环境名称（如：Development、Test、Production）</param>
        /// <returns>日志记录器配置</returns>
        public static LoggerConfiguration FromJsonFile(string jsonFilePath, string environment)
        {
            if (string.IsNullOrEmpty(jsonFilePath))
                throw new ArgumentNullException(nameof(jsonFilePath));

            // 构造环境特定的文件名
            if (!string.IsNullOrEmpty(environment))
            {
                var fileInfo = new FileInfo(jsonFilePath);
                var directory = fileInfo.DirectoryName;
                var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(jsonFilePath);
                var extension = fileInfo.Extension;
                
                var environmentFilePath = Path.Combine(directory, $"{fileNameWithoutExtension}.{environment}{extension}");
                if (File.Exists(environmentFilePath))
                {
                    jsonFilePath = environmentFilePath;
                }
            }

            if (!File.Exists(jsonFilePath))
                throw new FileNotFoundException($"配置文件未找到: {jsonFilePath}");

            try
            {
                var json = File.ReadAllText(jsonFilePath);
                return JsonConvert.DeserializeObject<LoggerConfiguration>(json);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException($"从JSON文件加载配置时出错: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 使用默认配置创建配置对象
        /// </summary>
        /// <returns>日志记录器配置</returns>
        public static LoggerConfiguration Default()
        {
            return new LoggerConfiguration();
        }

        /// <summary>
        /// 获取当前环境名称
        /// </summary>
        /// <returns>环境名称</returns>
        private static string GetCurrentEnvironment()
        {
            // 优先级：环境变量 > AppSettings配置 > 默认为空
            var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            if (string.IsNullOrEmpty(environment))
            {
                environment = Environment.GetEnvironmentVariable("ENVIRONMENT");
            }
            
            if (string.IsNullOrEmpty(environment))
            {
                try
                {
                    environment = ConfigurationManager.AppSettings["Environment"];
                }
                catch
                {
                    // 忽略配置读取异常
                }
            }

            return environment;
        }

        /// <summary>
        /// 获取配置节中的值
        /// </summary>
        /// <typeparam name="T">值的类型</typeparam>
        /// <param name="section">配置节</param>
        /// <param name="key">键名</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>配置值</returns>
        private static T GetConfigValue<T>(ConfigurationSection section, string key, T defaultValue)
        {
            try
            {
                var property = section.ElementInformation.Properties[key];
                if (property != null && property.Value != null)
                {
                    if (typeof(T).IsEnum)
                    {
                        return (T)Enum.Parse(typeof(T), property.Value.ToString(), true);
                    }
                    
                    return (T)Convert.ChangeType(property.Value, typeof(T));
                }
            }
            catch
            {
                // 转换失败时返回默认值
            }

            return defaultValue;
        }
    }
}